package com.cn.netty.basic;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;

import java.nio.charset.StandardCharsets;
import java.util.concurrent.*;

@Slf4j
public class EchoServer {

  public static String property = System.getProperty("line.separator");
  public static ByteBuf delimiter = Unpooled.copiedBuffer(property.getBytes(StandardCharsets.UTF_8));



  public static void main(String[] args) {
//    EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
//    ServerBootstrap bootstrap = new ServerBootstrap();
//    ServerBootstrap serverBootstrap = bootstrap.group(eventLoopGroup)

    ThreadFactory commonLangThreadFactory0 = new BasicThreadFactory.Builder()
            .namingPattern("netty-outhandler0-%d")
            .build();
    ExecutorService exec0 = new ThreadPoolExecutor(10, 10,
            1000L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(10), commonLangThreadFactory0);
    for (int i = 0; i < 10; i++) {
        exec0.submit(new Runnable() {
            @Override
            public void run() {
                log.info("basicThreadFactory");
            }
        });
    }

    ExecutorService exec1 = new ThreadPoolExecutor(10, 10,
            1000L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(10), new BasicThreadFactory.Builder()
            .namingPattern("netty-outhandler1-%d")
            .build());
    for (int i = 0; i < 10; i++) {
        exec1.submit(new Runnable() {
            @Override
            public void run() {
                log.info("basicThreadFactory");
            }
        });
    }


    ThreadFactory commonLangThreadFactory = new BasicThreadFactory.Builder()
            .namingPattern("netty-master-%d")
            .build();
    ExecutorService exec = new ThreadPoolExecutor(1, 1,
            1000L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(10), commonLangThreadFactory);
    for (int i = 0; i < 2; i++) {
        exec.submit(() -> {
            log.info("--记忆中的颜色是什么颜色---");
        });
    }

    EventLoopGroup eventLoopGroup0 = new NioEventLoopGroup(10, exec0);
    EventLoopGroup eventLoopGroup1 = new NioEventLoopGroup(10, exec1);

    EventLoopGroup boss = new NioEventLoopGroup(1, commonLangThreadFactory);
//    EventLoopGroup boss = new NioEventLoopGroup(1);
    EventLoopGroup work = new NioEventLoopGroup(1);
    ServerBootstrap bootstrap = new ServerBootstrap();
    ServerBootstrap serverBootstrap = bootstrap.group(boss, work)
            .channel(NioServerSocketChannel.class)
            .option(ChannelOption.SO_BACKLOG, 1024)
            .localAddress(9999)
//            .handler(new ChannelInitializer<SocketChannel>() {
//              @Override
//              protected void initChannel(SocketChannel ch) throws Exception {
//                ch.pipeline().addLast(new LoggingHandler());
//              }
//            })
            .childHandler( //注意 这是个childHandler
                    new ChannelInitializer<SocketChannel>() {
                      @Override
                      protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new LoggingHandler());
                        ch.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, delimiter)); //入站 通过分隔符，解决粘包拆包问题

                        ch.pipeline().addLast(new EchoServerOutboundHandlerOne());  //出站
//                        ch.pipeline().addLast(eventLoopGroup1,new EchoServerOutboundHandlerOne());  //出站
                        ch.pipeline().addLast(eventLoopGroup1,new EchoServerOutboundHandlerZero());  //出站 测试->为handler 单独设置 eventLoopGroup
                        ch.pipeline().addLast(new EchoServerHandler()); //入站
                        ch.pipeline().addLast(eventLoopGroup0,new EchoServerHandler()); //入站 测试->为handler 单独设置 eventLoopGroup
                      }
                    });
    try {
      /*异步绑定到服务器，sync()会阻塞到完成*/
      ChannelFuture bind = serverBootstrap.bind();
      bind.addListener(new GenericFutureListener<Future<? super Void>>() {
        @Override
        public void operationComplete(Future<? super Void> future) throws Exception {
          log.info("服务器启动完成。");
        }
      });
      ChannelFuture f = bind.sync();

      /*阻塞当前线程，直到服务器的ServerChannel被关闭*/
      f.channel().closeFuture().sync();
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }

}
